package covertjava.bytecode;
import java.io.IOException;
import java.util.regex.Pattern;

import org.apache.bcel.*;
import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;

/**
 * <p>Generates classes on the fly using Apache BCEL library</p>
 * <p>Copyright: Copyright (c) 2004 Sams Publishing</p>
 * @author Alex Kalinovsky
 * @version 1.0
 */
public class ClassGenerator {

    public static void main(String[] args) throws IOException {
        if (args.length != 2) {
            System.out.println("Syntax: ClassGenerator <full class name> <field name pattern>");
            System.exit(1);
        }
        JavaClass sourceClass = Repository.lookupClass(args[0]);
        ClassGenerator generator = new ClassGenerator();
        JavaClass valueClass = generator.generateValueObject(sourceClass, args[1]);
        valueClass.dump(valueClass.getClassName() + ".class");
    }

    /**
     * Generates a value object class for the given class
     */
    public JavaClass generateValueObject(
        JavaClass sourceClass,
        String fieldPattern) {
        String newName = sourceClass.getClassName() + "Value";
        ClassGen classGen = new ClassGen(
                newName,
                "java.lang.Object",
                newName,
                Constants.ACC_PUBLIC | Constants.ACC_SUPER,
                new String[] { "java.io.Serializable" });
        Field[] fields = sourceClass.getFields();
        for (int i = 0; i < fields.length; i++) {
            if (Pattern.matches(fieldPattern, fields[i].getName())) {
                int skipFlags = Constants.ACC_STATIC | Constants.ACC_TRANSIENT;
                if ((fields[i].getAccessFlags() & skipFlags) == 0) {
                    fields[i].setAccessFlags(Constants.ACC_PUBLIC);
                    addField(classGen, fields[i]);
                }
            }
        }
        return classGen.getJavaClass();
    }

    protected void addField(ClassGen classGen, Field field) {
        System.out.println("Generating field " + field.getName());
        FieldGen fieldGen = new FieldGen(field, classGen.getConstantPool());
        classGen.addField(fieldGen.getField());
    }
}
